<?php
/**
 * Created by PhpStorm.
 * User: ownfi
 * Date: 2017-04-05
 * Time: 21:59
 */

namespace App\Services\Impl;


use App\Common\Constant\Params;
use App\Events\MasterOrderRefund;
use App\Events\MasterPunished;
use App\Events\OrderComplained;
use App\Events\OrderRefunded;
use App\Models\Order;
use App\Models\OrderComplain;
use App\Models\OrderOffer;
use App\Models\OrderRefund;
use App\Models\OrderStatus;
use App\Services\IRefundService;
use App\Services\ISystemService;
use DB;
use Log;

class RefundServiceImpl implements IRefundService
{

    public function listRefund($master_id)
    {
        $orderIds = OrderOffer::where(["master_id"=>$master_id,"status"=>Params::OFFER_STATUS_EMPLOYED])->select('order_id')->get()->pluck('order_id');
        if ($orderIds->isEmpty()){
            return Collection::make([]);
        }
        $orderIds = OrderRefund::whereIn("order_id",$orderIds)->get()->pluck('order_id');
        if ($orderIds->isEmpty()){
            return Collection::make([]);
        }
        return Order::whereIn("id",$orderIds)->with('status','merchant','refunds')->get()->sortByDesc(function ($item, $key) {
            return $item->refund->add_time;
        });
    }

    public function agreeRefund($refund_id)
    {
        $refund = OrderRefund::find($refund_id);
        if (!$refund){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss refund'));
            return false;
        }

        return $refund->update([
            'refund_result_time'=>time(),
            'refund_result_type'=>Params::ORDER_REFUND_RESULT_AGREE,
        ]) && event(new MasterOrderRefund($refund_id));
    }

    public function applyArbitrate($refund_id, $result_type, $result_reason, $result_amount)
    {
        $refund = OrderRefund::find($refund_id);
        if (!$refund){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss refund'));
            return false;
        }

        if ($result_type == Params::ORDER_ARBITRATE_RESULT_AGREE_FULL){
            $result_amount = $refund->refund_amount;
        }else if ($result_type == Params::ORDER_ARBITRATE_RESULT_AGREE_PART){
            if (!$result_amount){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss param: $result_amount'));
                return false;
            }
        }else if ($result_type == Params::ORDER_ARBITRATE_RESULT_DISAGREE){
            $result_amount = null;
        }

        $ret = $refund->update([
                'arbitrate_result_time'=>time(),
                'arbitrate_result_type'=>$result_type,
                'arbitrate_result_amount'=>$result_amount,
                'arbitrate_result_reason'=>$result_reason
            ]);
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'refund update fail'));
            return false;
        }

        if (($result_type == Params::ORDER_ARBITRATE_RESULT_AGREE_FULL) && ($refund->refund_type == Params::ORDER_REFUND_FULL)){
            $ret = OrderStatus::where('order_id',$refund->order_id)->take(1)->update([
                'except_status'=>Params::ORDER_EXCEPT_ARBITRATED,
                'arbitrate_status'=>Params::ORDER_ARBITRATE_RETURN_FULL,
            ]);
        }else if (($result_type == Params::ORDER_ARBITRATE_RESULT_AGREE_FULL) && ($refund->refund_type == Params::ORDER_REFUND_PART)){
            $ret = OrderStatus::where('order_id',$refund->order_id)->take(1)->update([
                'except_status'=>Params::ORDER_EXCEPT_NORMAL,
                'arbitrate_status'=>Params::ORDER_ARBITRATE_RETURN_PART,
            ]);
        }else if ($result_type == Params::ORDER_ARBITRATE_RESULT_AGREE_PART){
            $ret = OrderStatus::where('order_id',$refund->order_id)->take(1)->update([
                'except_status'=>Params::ORDER_EXCEPT_NORMAL,
                'arbitrate_status'=>Params::ORDER_ARBITRATE_RETURN_PART,
            ]);
        }else if ($result_type == Params::ORDER_ARBITRATE_RESULT_DISAGREE){
            $ret = OrderStatus::where('order_id',$refund->order_id)->take(1)->update([
                'except_status'=>Params::ORDER_EXCEPT_NORMAL,
                'arbitrate_status'=>Params::ORDER_ARBITRATE_REFUSE,
            ]);
        }else{
            $ret = false;
        }
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'status update fail'));
            return false;
        }

        if ($result_type != Params::ORDER_ARBITRATE_RESULT_DISAGREE){
            $ret = event(new OrderRefunded($refund->id,$result_amount));
        }

        return $ret;
    }

    public function applyComplain($complain_id, $result_type, $result_reason, $punish_amount)
    {
        $complain = OrderComplain::find($complain_id);
        if (!$complain){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss complain'));
            return false;
        }

        if ($result_type == Params::COMPLAIN_RESULT_AGREE){
            if (!$punish_amount){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss param: $punish_amount'));
                return false;
            }
            $ret = $complain->update([
                'oc_handle_status'=>Params::COMPLAIN_STATUS_OK,
                'oc_handle_result'=>$result_type,
                'oc_handle_time'=>time(),
                'oc_handle_explain'=>$result_reason,
                'oc_punish_amount'=>$punish_amount
            ]);
        }else if ($result_type == Params::COMPLAIN_RESULT_DISAGREE){
            $ret = $complain->update([
                'oc_handle_status'=>Params::COMPLAIN_STATUS_FAIL,
                'oc_handle_result'=>$result_type,
                'oc_handle_time'=>time(),
                'oc_handle_explain'=>$result_reason,
            ]);
        }else{
            $ret = false;
        }
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'complain update fail'));
            return false;
        }

        $ret = event(new OrderComplained($complain_id));
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'event trigger fail'));
            return false;
        }

        if ($result_type == Params::COMPLAIN_RESULT_AGREE){
            $ret = event(new MasterPunished($complain_id,$punish_amount));
        }

        return $ret;
    }

}